use std::{
    collections::HashMap,
    sync::{Arc, Mutex},
};
use tokio::time::{sleep, timeout, Duration};

use model_graph_types::{
    container::workflow::{
        WaitStatement, WorkflowBlockExecuteResult, WorkflowBlockExecuteResultBuilder,
        WorkflowBlockExecuteResultStatus, WorkflowErrorStrategy,
    },
    modeling::Value,
};

use crate::workflow::{
    blocks::{if_else::workflow_conditions_result, statements::_utils::query_value_with_variables},
    context::WorkflowContext,
};

pub async fn execute(
    statement: &WaitStatement,
    context: Arc<Mutex<WorkflowContext>>,
) -> anyhow::Result<WorkflowBlockExecuteResult> {
    let error_strategy = statement.error_strategy.clone();

    let result = _execute(statement, context).await;
    match result {
        Ok(v) => {
            if let Some(Value::Boolean(true)) = v.get(&String::from("timeout")) {
                Ok(WorkflowBlockExecuteResultBuilder::default()
                    .status(WorkflowBlockExecuteResultStatus::Succeeded)
                    .source_handle("timeout-branch")
                    .result(v)
                    .build()?)
            } else {
                Ok(WorkflowBlockExecuteResultBuilder::default()
                    .status(WorkflowBlockExecuteResultStatus::Succeeded)
                    .source_handle("source")
                    .result(v)
                    .build()?)
            }
        }
        Err(err) => {
            if let Some(error_strategy) = error_strategy {
                match error_strategy {
                    WorkflowErrorStrategy::FailBranch => {
                        Ok(WorkflowBlockExecuteResultBuilder::default()
                            .status(WorkflowBlockExecuteResultStatus::Succeeded)
                            .source_handle("fail-branch")
                            .build()?)
                    }
                    _ => Ok(WorkflowBlockExecuteResultBuilder::default()
                        .status(WorkflowBlockExecuteResultStatus::Succeeded)
                        .source_handle("source")
                        .build()?),
                }
            } else {
                Ok(WorkflowBlockExecuteResultBuilder::default()
                    .status(WorkflowBlockExecuteResultStatus::Succeeded)
                    .source_handle("source")
                    .build()?)
            }
        }
    }
}

pub async fn _execute(
    statement: &WaitStatement,
    context: Arc<Mutex<WorkflowContext>>,
) -> anyhow::Result<HashMap<String, Value>> {
    let interval = if let Some(interval) = &statement.interval {
        *interval
    } else {
        600000_u64
    };
    //
    let mut result: HashMap<String, Value> = HashMap::new();
    if let Some(case) = &statement.cases {
        if let Some(time_out) = &statement.timeout {
            if let Ok(_) = timeout(
                Duration::from_millis(*time_out),
                Box::pin(async move {
                    loop {
                        tracing::debug!("wait执行一次循环");
                        //
                        let conditions = &case.conditions;
                        let operator = &case.logical_operator;

                        if let Ok(case_result) =
                            workflow_conditions_result(operator, conditions, context.clone())
                        {
                            if case_result {
                                //
                                break;
                            }
                        }
                        //sleep
                        sleep(Duration::from_millis(interval)).await;
                    }
                    true
                }),
            )
            .await
            {
                //条件满足，退出
                tracing::debug!("返回数据成功!");
                result.insert(String::from("timeout"), Value::Boolean(false));
                Ok(result)
            } else {
                result.insert(String::from("timeout"), Value::Boolean(true));
                tracing::debug!("请求超时!");
                Ok(result)
            }
        } else {
            loop {
                tracing::debug!("wait执行一次循环");
                //
                let conditions = &case.conditions;
                let operator = &case.logical_operator;

                if let Ok(case_result) =
                    workflow_conditions_result(operator, conditions, context.clone())
                {
                    if case_result {
                        //
                        break;
                    }
                }
                //sleep
                sleep(Duration::from_millis(interval)).await;
            }
            return Ok(result);
        }
    } else {
        return Err(anyhow::anyhow!("没有设置条件！"));
    }
}
